package com.gobygang.client.facebook;

import com.gobygang.client.Gobygang;
import com.gobygang.client.GobygangPresenter;
import com.gobygang.client.Session;
import com.gobygang.client.Session.UserAgent;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;

public class FacebookApi {


	/**
	 * This is the entry point method.
	 */
	//public static void  waitForAPI(final TaxiGangMain main, final TaxiGangMain.ThenRenderRestOfApp thenRenderRestOfApp,final PushButton fbLoginButton){
	public static void  waitForAPI(final GetUserDetailsCallback getUserDetailsCallback){
		if (!Gobygang.testing){
			//LoginPanel.fbLoginButton.setHTML("<fb:login-button></fb:login-button>");	
			exportMethods(GobygangPresenter.getInstance());
			if (!Session.getInstance().getLocalHost()){
				initFacebookAPIGobygang();
			}else{
				initFacebookAPIIncubator();
			}
			if (Session.getInstance().getUserAgent()==UserAgent.FB || Session.getInstance().getUserAgent()==UserAgent.FB_WEBKIT ){
				try{
					fbGetSession( getUserDetailsCallback );	
				} catch (Exception ex){
					////Log.error(ex.getMessage());
				}
				//fbGetSession ( thenRenderRestOfApp );
			} else {
				//fbGetSession ( thenRenderRestOfApp );
				//fbGetLoginStatus ( thenRenderRestOfApp );
				try{
					fbGetSession( getUserDetailsCallback );				
				} catch (Exception ex){
					//Log.error(ex.getMessage());
				}
			}
			//waitForFBTimeout(presenter,0);
		} else {
			getUserDetailsCallback.onSuccess(ConnectState.connected);
		}
	}

	//	private static void  waitForFBTimeout(final WelcomePresenter presenter,final Integer counter){
	//		Timer timer = new Timer() {
	//			public void run() {
	//				if (counter > 20){
	//					presenter.onFacebookTimeout();
	//					return;
	//				}
	//				waitForFBTimeout(presenter,counter+1);
	//			}
	//		};
	//		timer.schedule(400);
	//	}


	public static native void fbGetLoginStatus(AsyncCallback<ConnectState> callback)/*-{
		alert("fbGetLoginStatus")
    var cs;
    var uid = "unknown";
    $wnd.FB.getLoginStatus(function(response) {
    	  if (response.status === 'connected') {
    			alert("connected getLoginStatus"+response.authResponse.userID);
          		cs=@com.gobygang.client.facebook.ConnectState::connected;
          		uid=response.authResponse.userID;
    	  } else {
    			alert("not connected getLoginStatus");
                cs=@com.gobygang.client.facebook.ConnectState::userNotLoggedIn;
    	  }
           @com.gobygang.client.facebook.FacebookApi::waitUntilReadySuccess(Lcom/google/gwt/user/client/rpc/AsyncCallback;Lcom/gobygang/client/facebook/ConnectState;Ljava/lang/String;)(callback,cs,uid);

    	});
	}-*/;

	public static native void fbGetSession(AsyncCallback<ConnectState> callback)/*-{
    	var cs;
    	var uid;
    	var authResponse = $wnd.FB.getAuthResponse();
    	  if (authResponse) {
    			//alert("connected fbGetSession"+response.authResponse.userID);
          		cs=@com.gobygang.client.facebook.ConnectState::connected;
          		uid=authResponse.userID;
    	  } else {
    			//alert("not connected fbGetSession");
                cs=@com.gobygang.client.facebook.ConnectState::userNotLoggedIn;
    	  }
           @com.gobygang.client.facebook.FacebookApi::waitUntilReadySuccess(Lcom/google/gwt/user/client/rpc/AsyncCallback;Lcom/gobygang/client/facebook/ConnectState;Ljava/lang/String;)(callback,cs,uid);

	}-*/;


	public static native void fbLogin(AsyncCallback<ConnectState> callback)/*-{
var cs;
var uid;
$wnd.FB.login(function(response) {
  if (response.authResponse) {
		//alert("connected over fb.login"+response.authResponse.userID);
  		cs=@com.gobygang.client.facebook.ConnectState::connected;
  		uid=response.authResponse.userID;
  		$wnd.onAPICall(callback, response, response.error);
  		
  } else {
		//alert("not connected over fb.login");
        cs=@com.gobygang.client.facebook.ConnectState::userNotLoggedIn;
        uid=-1;
  }

}, {perms:'publish_stream'});

}-*/;

	public static native void fbLogin()/*-{
		var cs;
		var uid;
		$wnd.FB.login(function(response) {
  		if (response.authResponse) {
			//alert("connected over fb.login"+response.authResponse.userID);
  			cs=@com.gobygang.client.facebook.ConnectState::connected;
  			uid=response.authResponse.userID;  		
  		} else {
			//alert("not connected over fb.login");
        	cs=@com.gobygang.client.facebook.ConnectState::userNotLoggedIn;
        	uid=-1;
  		}
	});

}-*/;

	public static native void postTaxigang(String path, String message,String tglink, AsyncCallback<ConnectState> callback)/*-{
	var cs;
	var uid;
	$wnd.FB.login(function(response) {
	  if (response.authResponse) {
			//alert("connected over fb.login"+response.authResponse.userID);
			
      		cs=@com.gobygang.client.facebook.ConnectState::connected;
      		uid=response.authResponse.userID;
      		
      		var body = message;
      		var lk = tglink;
      		//176271679134329
			$wnd.FB.api(path, 'post', { message: body , link: lk }, function(response) {
			if (!response) {
			    alert('Error occured');
			} else if (response.error) {
      			alert("error from post"+response.error);
			    // call callback with the actual error
				$wnd.onAPICall(callback, null, response.error);
			} else if (response.data) {
      			//alert("ok from post"+response.data);
				// call callback with the actual json-array
				$wnd.onAPICall(callback, response.data, null);
			} else {
				//alert($wnd.dump(response));
				// call callback with the actual json-object
				$wnd.onAPICall(callback, response, null);
			} 
			
      		});
      		
      		
	  } else {
			//alert("not connected over fb.login");
            cs=@com.gobygang.client.facebook.ConnectState::userNotLoggedIn;
            uid=-1;
	  }

	}, {scope: 'publish_stream'});

}-*/;

	public static native void getEmail(AsyncCallback<ConnectState> callback)/*-{
	var cs;
	var uid;
	var email;
	$wnd.FB.login(function(response) {
	  if (response.authResponse) {
       	  	uid=response.authResponse.userID;
			$wnd.FB.api('/me', function (response) {
      	  		cs=@com.gobygang.client.facebook.ConnectState::connected;
       	  		email=response.email;
          		@com.gobygang.client.facebook.FacebookApi::waitUntilReadySuccess2(Lcom/google/gwt/user/client/rpc/AsyncCallback;Lcom/gobygang/client/facebook/ConnectState;Ljava/lang/String;Ljava/lang/String;)(callback,cs,uid,email);
			});
      		
      		
	  } else {
			//alert("not connected over fb.login");
            cs=@com.gobygang.client.facebook.ConnectState::userNotLoggedIn;
            uid=-1;
	  }

	}, {scope: 'email'});

}-*/;

	public static native void getAccessToken(AsyncCallback<ConnectState> callback)/*-{
			$wnd.FB.api('oauth/access_token', 'get', { client_id: '141025345926512',  client_secret: '136cdc4e7866c592fb78351da0947cae', grant_type: 'client_credentials'}, function(response) {
			if (!response) {
			    alert('Error occured');
			} else if (response.error) {
      			alert("error from post"+response.error);
			    // call callback with the actual error
				$wnd.onAPICall(callback, null, response.error);
			} else if (response.data) {
      			alert("ok from post"+response.data);
				// call callback with the actual json-array
				$wnd.onAPICall(callback, response.data, null);
			} else {
				alert($wnd.dump(response));
				// call callback with the actual json-object
				$wnd.onAPICall(callback, response, null);
			} 
			
      		});

}-*/;

	/**
	 * Fire callback when we have connect state
	 */
	static void waitUntilReadySuccess(AsyncCallback<ConnectState> callback, ConnectState connectState, String uid) {
		Session.getInstance().getLoginInfo().setId(uid);
		callback.onSuccess ( connectState );
	}

	static void waitUntilReadySuccess2(AsyncCallback<ConnectState> callback, ConnectState connectState, String uid, String email) {
		Session.getInstance().getLoginInfo().setId(uid);
		Session.getInstance().getLoginInfo().setEmailAddress(email);
		callback.onSuccess ( connectState );
	}

	public static void getUserDetails(AsyncCallback<JavaScriptObject> callback){
		if (!Gobygang.testing){
			FacebookApi.waitUntilUserDetailsReady(callback);			
		} else {
			//UserJso fbUser = new UserJso();
			callback.onSuccess(null);
		}
	}
	public static native void waitUntilUserDetailsReady(AsyncCallback<JavaScriptObject> callback)/*-{
		$wnd.FB.api("/me", function(response) {
			// on error, this callback is never called in Firefox - why?
			if (!response) {
			    alert('Error occured');
			} else if (response.error) {
				alert($wnd.dump(response));
			    // call callback with the actual error
				$wnd.onAPICall(callback, null, response.error);
			} else if (response.data) {
				//alert($wnd.dump(response));
				// call callback with the actual json-array
				$wnd.onAPICall(callback, response.data, null);
			} else {
				//alert($wnd.dump(response));
				// call callback with the actual json-object
				$wnd.onAPICall(callback, response, null);
			} 
		});
	}-*/;


	private static native void callAPI(String path, AsyncCallback<JavaScriptObject> callback) /*-{
	$wnd.FB.api(path, function(response) {
		// on error, this callback is never called in Firefox - why?
		if (!response) {
		    alert('Error occured');
		} else if (response.error) {
		    alert('Error occured2');
			//alert($wnd.dump(response));
		    // call callback with the actual error
			$wnd.onAPICall(callback, null, response.error);
		} else if (response.data) {
			//alert(response.data);
			// call callback with the actual json-array
			$wnd.onAPICall(callback, response.data, null);
		} else {
			//alert("unknown");
			//alert($wnd.dump(response));
			// call callback with the actual json-object
			$wnd.onAPICall(callback, response, null);
		} 
	});
}-*/;

	private static native void postAPI(String path, AsyncCallback<JavaScriptObject> callback) /*-{
		var body = 'Reading JS SDK documentation';
		$wnd.FB.api('/me/feed', 'post', { message: body }, function(response) {
			if (!response) {
			    alert('Error occured');
			} else if (response.error) {
				alert($wnd.dump(response));
			    // call callback with the actual error
				$wnd.onAPICall(callback, null, response.error);
			} else if (response.data) {
				//alert($wnd.dump(response));
				// call callback with the actual json-array
				$wnd.onAPICall(callback, response.data, null);
			} else {
				//alert($wnd.dump(response));
				// call callback with the actual json-object
				$wnd.onAPICall(callback, response, null);
			} 
	});
	}-*/;

	public static native String initFacebookAPIGobygang()
	/*-{
	 	$wnd.FB.init({appId: '141025345926512', status: true, cookie: true, xfbml: true, oauth : true,  channelUrl: "http://www.gobygang.com/fb/channel.html"});
		$wnd.FB.Event.subscribe('auth.statusChange', function(response) {
		  if (response.authResponse) {
		    // A user has logged in, and a new cookie has been saved
		    $wnd.onLogin();
		  } else {
		    // The user has logged out, and the cookie has been cleared
		    $wnd.onLogout();
		  }		  			  	
		});
	}-*/;

	public static native String initFacebookAPIIncubator()
	/*-{
	 	$wnd.FB.init({appId: '148149315199545', status: true, cookie: true, xfbml: true, oauth : true});
		$wnd.FB.Event.subscribe('auth.statusChange', function(response) {
		  if (response.authResponse) {
		    // A user has logged in, and a new cookie has been saved
		    $wnd.onLogin();
		  } else {
		    // The user has logged out, and the cookie has been cleared
		    $wnd.onLogout();
		  }		  			  	
		});		
	}-*/;

	private static native JavaScriptObject initFacebookAPIAndGetSession()
	/*-{
    	var cs;
	 	$wnd.FB.init({appId: '141025345926512', status: true, cookie: true, xfbml: true, oauth : true});
	 	alert("init3");
		var session = $wnd.getAuthResponse();
		return session;	

	}-*/;


	public static native void fbLogout() /*-{
		$wnd.FB.logout();
	}-*/;

	/**
	 * To be called after an XFBML-tag has been inserted into the DOM
	 */
	public static native void parseDomTree() /*-{
		$wnd.FB.XFBML.parse();
	}-*/;

	public static native String parseFBML(String id) /*-{
	  $wnd.FB.XFBML.parse($doc.getElementById(id));

	}-*/; 
	private static native void exportMethods(GobygangPresenter instance) /*-{		
			$wnd.onLogin = function() {
			return instance.@com.gobygang.client.GobygangPresenter::onFacebookLogin()();
			}
			$wnd.onLogout = function() {
			return instance.@com.gobygang.client.GobygangPresenter::onFacebookLogout()();
			}
			$wnd.onAPICall = function(callback, response, exception) {
			return @com.gobygang.client.facebook.FacebookApi::onAPICall(Lcom/google/gwt/user/client/rpc/AsyncCallback;Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gwt/core/client/JavaScriptObject;)(callback, response, exception);
			}
		}-*/;

	public static void onAPICall(AsyncCallback<JavaScriptObject> callback,
			JavaScriptObject response, JavaScriptObject exception) {
		if (response != null) {
			callback.onSuccess(response);
		} else {
			ExceptionJso e = (ExceptionJso) exception;
			callback.onFailure(new Exception(e.getType() + ": " + e.getMessage()));
		}
	}

	//	public void onLogin() {
	//		// just to show that xfbml works here, as well
	//		fbProfile.setHTML("<span>"
	//				+ "<fb:profile-pic uid=loggedinuser facebook-logo=true></fb:profile-pic>"
	//				+ "Welcome, <fb:name uid=loggedinuser useyou=false></fb:name>.</span>");
	//
	//		// make sure the xfbml is rendered
	//		parseDomTree();
	//	}
	//
	//	public void onLogout() {
	//		fbProfile.setHTML("");
	//	}

	public static void getMe() {
		//Log.info("FacebookApi:getMe");
		callAPI("/me", new AsyncCallback<JavaScriptObject>() {

			@Override
			public void onFailure(Throwable caught) {
				Window.alert("error"+caught.getMessage());
			}

			@Override
			public void onSuccess(JavaScriptObject result) {
				UserJso fbUser = (UserJso) result;
				Window.alert(fbUser.getFullName());
			}
		});
	}

	public static void getEmail() {
		//Log.info("FacebookApi:getEmail");
		callAPI("/email", new AsyncCallback<JavaScriptObject>() {

			@Override
			public void onFailure(Throwable caught) {
				Window.alert("error"+caught.getMessage());
			}

			@Override
			public void onSuccess(JavaScriptObject result) {
				UserJso fbUser = (UserJso) result;
				Window.alert(fbUser.getEmail());
			}
		});
	}

	public void getFriends() {
		callAPI("/me/friends", new AsyncCallback<JavaScriptObject>() {
			@Override
			public void onFailure(Throwable caught) {
				Window.alert(caught.getMessage());

			}

			@SuppressWarnings("unchecked")
			@Override
			public void onSuccess(JavaScriptObject result) {
				JsArray<UserRefJso> friends = (JsArray<UserRefJso>) result;
				StringBuffer buf = new StringBuffer();
				for (int i = 0, n = friends.length(); i < n; ++i) {
					buf.append(friends.get(i).getName());
					if (i < n) {
						buf.append(", ");
					}
				}

				Window.alert("" + buf);
			}
		});
	}



	private static native void getPermission(String path, AsyncCallback<JavaScriptObject> callback) /*-{
		$wnd.FB.login(function(response) {
		   if (response.authResponse) {
		     console.log('Welcome!  Fetching your information.... ');
		     $wnd.FB.api('/me', function(response) {
		       console.log('Good to see you, ' + response.name + '.');
		       FB.logout(function(response) {
		         console.log('Logged out.');
		       });
		     });
		   } else {
		     console.log('User cancelled login or did not fully authorize.');
		   }
		 }, {scope: 'publish_stream'});
	}-*/;

	public static native void fbLoginAndPost()/*-{
	var cs;
	var uid;
	$wnd.FB.login(function(response) {
	  if (response.authResponse) {
			//alert("connected over fb.login"+response.authResponse.userID);
      		cs=@com.gobygang.client.facebook.ConnectState::connected;
      		uid=response.authResponse.userID;
	  } else {
			//alert("not connected over fb.login");
            cs=@com.gobygang.client.facebook.ConnectState::userNotLoggedIn;
            uid=-1;
	  }

	}, {scope: 'publish_stream'});

}-*/;


}
